package com.iiapk.gridview.view;

import java.util.List;
import android.app.Service;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Vibrator;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
import com.iiapk.gridview.Constant;
import com.iiapk.gridview.R;
import com.iiapk.gridview.database.GridItem;

public class DragGridView extends GridView {
	
	public static boolean isMove=false;
	public static boolean isChangingPage=false;
	public static boolean isDelDark = false;
	
	private Context mContext;
	private List<GridItem> mList;
	private ViewGroup fromView;
	private ImageView ivDrag;
	private WindowManager windowManager;
	private WindowManager.LayoutParams windowParams;
	private PageListener pageListener;
	private ItemChangeListener itemChangeListener;
	private Animation atoB;
	private Animation btoA;
	private Animation delDone;
	
	private int mLastX,xtox;
	private boolean isCountXY=false;
	private int mLastY,ytoy;
	private int dragPosition;
	private int dropPosition;
	private int moveNum;
	private int stopCount=0;

	public DragGridView(Context context,List<GridItem> list) {
		super(context, null);
		mList=list;
		mContext =context;
		setNumColumns(2);
		setHorizontalSpacing(0);
		setVerticalSpacing(0);
		setSelector(R.drawable.selector_null);
		this.setAdapter(new DragGridAdapter());
	}
	
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		if (ev.getAction() == MotionEvent.ACTION_DOWN) {
			return setOnItemLongClickListener(ev);
		}
		return super.onInterceptTouchEvent(ev);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		if (ivDrag != null && dragPosition != AdapterView.INVALID_POSITION) {
			int x = (int) ev.getX();
			int y = (int) ev.getY();
			switch (ev.getAction()) {
			case MotionEvent.ACTION_MOVE:
				if(!isCountXY) {
					xtox = x-mLastX;
					ytoy = y-mLastY;
					isCountXY= true;
				}
				onDrag(x, y);
				break;
			case MotionEvent.ACTION_UP:
				stopDrag();
				onDrop(x, y);
				break;
			}
		}
		return super.onTouchEvent(ev);
	}
	
	public boolean setOnItemLongClickListener(final MotionEvent ev) {
		this.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
			@Override
			public boolean onItemLongClick(AdapterView<?> arg0, View arg1,int arg2, long arg3) {
				Vibrator vibrator = (Vibrator) mContext.getSystemService(Service.VIBRATOR_SERVICE);
				vibrator.vibrate(100);
				isMove = true; 
				isCountXY=false;
				int x = (int) ev.getX();
				int y = (int) ev.getY();
				mLastX=x;
				mLastY=y;
				dragPosition = dropPosition = arg2;
				if (dragPosition == AdapterView.INVALID_POSITION) {
					return false;
				}
				fromView = (ViewGroup) getChildAt(dragPosition - getFirstVisiblePosition());
				fromView.destroyDrawingCache();
				fromView.setDrawingCacheEnabled(true);
				fromView.setDrawingCacheBackgroundColor(0xff6DB7ED);
				Bitmap bm = Bitmap.createBitmap(fromView.getDrawingCache());
				Bitmap bitmap = Bitmap.createBitmap(bm, 8, 8, bm.getWidth()-16, bm.getHeight()-8);
				startDrag(bitmap, x, y);
				return false;
			};
		});
		return super.onInterceptTouchEvent(ev);
	}
	
	private void startDrag(final Bitmap bm, final int x, final int y) {
		windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
		Animation disappear= AnimationUtils.loadAnimation(getContext(), R.anim.griditem_longclick_disappear);
		disappear.setAnimationListener(new Animation.AnimationListener() {
			@Override
			public void onAnimationStart(Animation animation) {
			}
			@Override
			public void onAnimationRepeat(Animation animation) {
			}
			@Override
			public void onAnimationEnd(Animation animation) {
				fromView.setVisibility(8);
				stopDrag();
				windowParams = new WindowManager.LayoutParams();
				windowParams.gravity = Gravity.TOP | Gravity.LEFT;
				windowParams.x = fromView.getLeft()+28;
				windowParams.y = fromView.getTop()+(int)(40*Constant.screenDensity)+8;
				windowParams.alpha = 0.8f;
				windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
				windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
				ivDrag = new ImageView(getContext());
				ivDrag.setImageBitmap(bm);
				windowManager.addView(ivDrag, windowParams);
			}
		});
		fromView.startAnimation(disappear);
		//pageListener.page(1,-100);
	}
	
	private void stopDrag() {
		if (ivDrag != null) {
			windowManager.removeView(ivDrag);
			ivDrag = null;
		}
	}
	
	private void onDrag(int x, int y) {
		if (ivDrag != null) {
			windowParams.alpha = 0.8f;
			windowParams.x = (x-mLastX-xtox)+fromView.getLeft()+28- moveNum*Constant.screenWidth;
			windowParams.y = (y-mLastY-ytoy)+fromView.getTop()+(int)(40*Constant.screenDensity)+8;
			windowManager.updateViewLayout(ivDrag, windowParams);
		}
		if((x>(Constant.screenWidth/2 - 100) && x<(Constant.screenWidth/2+100)) 
				&& (y>Constant.screenHeight-200)){
			pageListener.page(2,-100);
			return;
		}
		if(isDelDark){
			pageListener.page(3,-200);
		}
		if(moveNum>0){
			if((x>=(moveNum+1)*Constant.screenWidth-20*Constant.screenDensity || 
					x<=moveNum*Constant.screenWidth)&&!isChangingPage) 
				stopCount++;
			else	
				stopCount=0;
			
			if(stopCount>10){
				stopCount=0;
				if(x>=(moveNum+1)*Constant.screenWidth-20*Constant.screenDensity &&
						ScrollLayout.curentPage<ScrollLayout.countPages-1){
					isChangingPage=true;
					pageListener.page(0,++ScrollLayout.curentPage);
					moveNum++;
				}
				else if(x<=moveNum*Constant.screenWidth && ScrollLayout.curentPage>0) {
					isChangingPage=true;
					pageListener.page(0,--ScrollLayout.curentPage);
					moveNum--;
				}
			}
		}else {
			//开始MOVE
			if((x>=(moveNum+1)*Constant.screenWidth-20*Constant.screenDensity || 
					x<=moveNum*Constant.screenWidth)&&!isChangingPage) 
				stopCount++;
			else	
				stopCount=0;
			
			if(stopCount>10){
				stopCount=0;
				if(x>=(moveNum+1)*Constant.screenWidth-20*Constant.screenDensity && 
						ScrollLayout.curentPage<ScrollLayout.countPages-1){
					isChangingPage=true;
					pageListener.page(0,++ScrollLayout.curentPage);
					moveNum++;
				}
				else if(x<=moveNum*Constant.screenWidth && ScrollLayout.curentPage>0) {
					isChangingPage=true;
					pageListener.page(0,--ScrollLayout.curentPage);
					moveNum--;
				}
			}
		}
	}
	
	private void onDrop(int x, int y) {
		fromView.setDrawingCacheBackgroundColor(0);
		isMove = false;
		if(isDelDark){
			delDone = getDelAnimation(x,y);
			delDone.setAnimationListener(new Animation.AnimationListener() {
				@Override
				public void onAnimationStart(Animation animation) {}
				@Override
				public void onAnimationRepeat(Animation animation) {}
				@Override
				public void onAnimationEnd(Animation animation) {
					//Configure.removeItem = dragPosition;
					pageListener.page(5,-300);
				}
			});
			fromView.setVisibility(0);
			fromView.startAnimation(delDone);
			return;
		}
		pageListener.page(4,-300);
		int tempPosition = pointToPosition(x- moveNum*Constant.screenWidth, y);
		if (tempPosition != AdapterView.INVALID_POSITION) {
			dropPosition = tempPosition;
		}
		if(moveNum!=0){
			itemChangeListener.change(dragPosition,dropPosition,moveNum);
			moveNum=0;
			return;
		}
		moveNum=0;
		ViewGroup toView = (ViewGroup)getChildAt(dropPosition-getFirstVisiblePosition());
		final DragGridAdapter adapter = (DragGridAdapter)this.getAdapter();
		if(dragPosition%2 == 0){
			atoB = getDownAnimation((dropPosition%2==dragPosition%2)?0:1,(dropPosition/2-dragPosition/2));
			if (dropPosition != dragPosition) toView.startAnimation(
					getMyAnimation((dragPosition%2==dropPosition%2)?0:-1,(dragPosition/2-dropPosition/2)));
		}	else{
			atoB= getDownAnimation((dropPosition%2==dragPosition%2)?0:-1,(dropPosition/2-dragPosition/2));
			if (dropPosition != dragPosition) toView.startAnimation(
					getMyAnimation((dragPosition%2==dropPosition%2)?0:1,(dragPosition/2-dropPosition/2)));
		}
		fromView.startAnimation(atoB);
		atoB.setAnimationListener(new Animation.AnimationListener() {
			@Override
			public void onAnimationStart(Animation arg0) {}
			@Override
			public void onAnimationRepeat(Animation arg0) {}
			@Override
			public void onAnimationEnd(Animation arg0) {
				adapter.exchange(dragPosition, dropPosition);
				adapter.notifyDataSetChanged();
			}
		});
	}
	
	public Animation getMyAnimation(float x,float y){
		TranslateAnimation go = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, 
				Animation.RELATIVE_TO_SELF, x, Animation.RELATIVE_TO_SELF, 0, 
				Animation.RELATIVE_TO_SELF, y);
		go.setFillAfter(true);
		go.setDuration(550);
		return go;
	}
	
	public Animation getDownAnimation(float x,float y){
		AnimationSet set = new AnimationSet(true);
		TranslateAnimation go = new TranslateAnimation(Animation.RELATIVE_TO_SELF, x, 
				Animation.RELATIVE_TO_SELF, x, Animation.RELATIVE_TO_SELF, y, 
				Animation.RELATIVE_TO_SELF, y);
		go.setFillAfter(true);go.setDuration(550);
		AlphaAnimation alpha = new AlphaAnimation(0.1f, 1.0f);
		alpha.setFillAfter(true);alpha.setDuration(550);
		ScaleAnimation scale = new ScaleAnimation(1.2f, 1.0f, 1.2f, 1.0f);
		scale.setFillAfter(true);scale.setDuration(550);
		set.addAnimation(go);set.addAnimation(alpha);set.addAnimation(scale);
		return set;
	}
	
	public Animation getDelAnimation(int x,int y){
		AnimationSet set = new AnimationSet(true);
		RotateAnimation rotate = new RotateAnimation(0, 360,Animation.RELATIVE_TO_SELF,0.5f,
				Animation.RELATIVE_TO_SELF,0.5f);
		rotate.setFillAfter(true);rotate.setDuration(550);
		AlphaAnimation alpha = new AlphaAnimation(1.0f, 0.0f);
		alpha.setFillAfter(true);alpha.setDuration(550);
		set.addAnimation(alpha);
		set.addAnimation(rotate);
		return set;
	}
	
	public class DragGridAdapter extends BaseAdapter {
		@Override
		public int getCount() {
			return mList.size();
		}
		@Override
		public Object getItem(int position) {
			return mList.get(position);
		}
		@Override
		public long getItemId(int position) {
			return mList.get(position).id;
		}
		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			convertView = LayoutInflater.from(mContext).inflate(R.layout.item_draggrid, null);
			ImageView imageView = (ImageView)convertView.findViewById(R.id.item_img);
			TextView textView = (TextView)convertView.findViewById(R.id.item_text);
			imageView.setImageResource(mList.get(position).icon);
			textView.setText(mList.get(position).text);
			return convertView;
		}
		public void exchange(int startPosition, int endPosition) {
			Object endObject = getItem(endPosition);
			Object startObject = getItem(startPosition);
			mList.add(startPosition, (GridItem) endObject);
			mList.remove(startPosition + 1);
			mList.add(endPosition, (GridItem) startObject);
			mList.remove(endPosition + 1);
		}
	}
	
	public void setPageListener(PageListener pageListener) {
		this.pageListener = pageListener;
	}

	public interface PageListener {
		void page(int cases,int page);
	}
	
	public void setOnItemChangeListener(ItemChangeListener itemChangeListener) {
		this.itemChangeListener = itemChangeListener;
	}

	public interface ItemChangeListener {
		void change(int from,int to,int count);
	}
	
}
